import {Component, STATE, ATTRIBUTE} from './framework.js'
import {enableGesture} from './gesture.js'
import {Timeline, Animation} from './animation.js'
import {ease} from './ease.js'
import './style.css'

export {STATE, ATTRIBUTE} from './framework.js'

export class Carousel extends Component {
    constructor() {
        super()
    }
    render() {
        this.root = document.createElement('div')
        this.root.classList.add('carousel')
        for (let record of this[ATTRIBUTE].src) {
            let child = document.createElement('div')
            child.style.backgroundImage = `url(${record.img})`
            this.root.appendChild(child)
        }
        enableGesture(this.root)
        let timeline = new Timeline()
        timeline.start()

        let t = 0 //时间计算
        let ax = 0
        let handler = null

        let children = this.root.children
        this[STATE].position = 0

        this.root.addEventListener('start', event => {
            timeline.pause()
            clearInterval(handler)
            let progress = (Date.now() - t) / 1500
            ax = ease(progress) * 500 - 500
        })

        this.root.addEventListener('tap', event => {
            this.triggerEvent('click', {
                position: this[STATE].position,
                data: this[ATTRIBUTE].src[this[STATE].position]
            })
        })

        this.root.addEventListener('pan', event => {
            let x = event.clientX - event.startX - ax
            let current = this[STATE].position - ((x - x % 500) / 500)
            for (let offset of [-1, 0, 1]) {
                let pos = current + offset
                pos = (pos % children.length + children.length) % children.length
                children[pos].style.transition = 'none'
                children[pos].style.transform = `translateX(${- pos * 500 + offset * 500 + x % 500}px)`
            }
            //console.log(event.clientX)
        })
        this.root.addEventListener('end', event => {
            timeline.reset()
            timeline.start()

            handler = setInterval(nextPicture, 3000)

            let x = event.clientX - event.startX - ax
            let current = this[STATE].position - ((x - x % 500) / 500)
            let direction = Math.round((x % 500) / 500)

            if (event.isFlick) {
                if (event.velocity < 0) {
                    direction = Math.ceil((x % 500) / 500)
                } else {
                    direction = Math.floor((x % 500) / 500)
                }
            }

            for (let offset of [-1, 0, 1]) {
                let pos = current + offset
                pos = (pos % children.length + children.length) % children.length
                children[pos].style.transition = 'none'
                timeline.add(new Animation(
                    children[pos].style, 'transform',
                    - pos * 500 + offset * 500 + x % 500,
                    - pos * 500 + offset * 500 + direction * 500,
                    1500, 0, ease,
                    v => `translateX(${v}px)`
                ))
            }
            this[STATE].position = this[STATE].position - ((x - x % 500) / 500) - direction
            this[STATE].position = (this[STATE].position % children.length + children.length) % children.length

            this.triggerEvent('change', {position: this[STATE].position})
        })

        let nextPicture = () => {
            let nextIndex = (this[STATE].position + 1) % children.length

            let current = children[this[STATE].position]
            let next = children[nextIndex]

            t = Date.now()

            timeline.add(new Animation(
                current.style, 'transform',
                - this[STATE].position * 500, - 500 - this[STATE].position * 500,
                1500, 0, ease,
                v => `translateX(${v}px)`
            ))
            timeline.add(new Animation(
                next.style, 'transform',
                500 - nextIndex * 500, - nextIndex * 500,
                1500, 0, ease,
                v => `translateX(${v}px)`
            ))

            this[STATE].position = nextIndex
            this.triggerEvent('Change', {position: this[STATE].position})
        }

        handler = setInterval(nextPicture, 3000)

/*
        //处理拖拽事件
        //下面的代码中将控件的宽度500写死了。
        this.root.addEventListener('mousedown', event => {
            let children = this.root.children
            let startX = event.clientX

            let move = event => {
                let x = event.clientX - startX
                let current = this[STATE].position - ((x - x % 500) / 500)
                for (let offset of [-1, 0, 1]) {
                    let pos = (current + offset + children.length) % children.length
                    children[pos].style.transition = 'none'
                    children[pos].style.transform = `translateX(${- pos * 500 + offset * 500 + x % 500}px)`
                }
            }
            let up = event => {
                //松开鼠标按键，恢复到最初的状态
                let x = event.clientX - startX
                let otherOffset = - Math.sign(Math.round(x / 500) - x + 250 * Math.sign(x))
                this[STATE].position = this[STATE].position - Math.round(x / 500)
                for (let offset of [0, otherOffset]) {
                    let pos = (this[STATE].position + offset + children.length) % children.length
                    children[pos].style.transition = ''
                    children[pos].style.transform = `translateX(${- pos * 500 + offset * 500}px)`
                }
                document.removeEventListener('mousemove', move)
                document.removeEventListener('mouseup', up)
            }
            document.addEventListener('mousemove', move)
            document.addEventListener('mouseup', up)
        })
*/
        /*
        let currentIndex = 0
        setInterval(() => {
            let children = this.root.children
            let nextIndex = (currentIndex + 1) % children.length

            let current = children[currentIndex]
            let next = children[nextIndex]

            //下面两个样式的设置是为了将下一元素出现在当前可显示区域的右侧，
            //同时要避免有动画。
            next.style.transition = 'none' //屏蔽元素自身的transition属性。
            next.style.transform = `translateX(${100 - nextIndex * 100}%)`

            //下一图片在可显示区域右侧准备好后，在下一帧动画开始的时候，
            //令当前图片从左侧出去，下一图片从右侧进来。
            setTimeout(() => {
                next.style.transition = '' //让元素自身的transition生效。
                current.style.transform = `translateX(${-100 - currentIndex * 100}%)`
                next.style.transform = `translateX(${- nextIndex * 100}%)`
                currentIndex = nextIndex
            }, 16) //16毫秒为浏览器中一帧的时间。
            //使用requestAnimationFrame的话，需要调用两次。
        }, 3000)
        */
        return this.root
    }
}

